// #include <stdio.h>
// #include <inttypes.h>
// #include "sdkconfig.h"
// #include "freertos/FreeRTOS.h"
// #include "freertos/task.h"
// #include "esp_chip_info.h"
// #include "esp_flash.h"
// #include "esp_system.h"

#include "bsp_wifi.h"
#include "commu_ota.h"
#include "audio_sr.h"
#include "bsp_sound.h"
#include "audio_encoder.h"
#include "audio_decoder.h"
#include "commu_ws.h"
#include "iot.h"
#include "display.h"
#include "int_led.h"
// dev

void wake_up_callback(void);
void vad_state_change_callback(vad_state_t state);

void text_cb(char *, int);
void bin_cb(char *, int);
void close_cb(void);
void audio_upload_task(void *args);

typedef struct
{
    RingbufHandle_t sr_2_encoder;     // 语音识别到编码器的缓冲区
    RingbufHandle_t encoder_2_ws;     // 编码器到通信的缓冲区
    RingbufHandle_t ws_2_decoder;     // 通信到解码器的缓冲区
    EventGroupHandle_t wait_hello_eg; // 事件组
} my_app_t;
my_app_t my_app;

typedef enum
{

    APP_IDLE,
    APP_CONNECTING,
    APP_SPEAKING,
    APP_LISTENING
} app_state_t;
app_state_t app_state = APP_IDLE;

my_sr_t mt_sr;

void app_create_buffer(void);

// void test(void *args)
// {
//     while (1)
//     {

//         printf("test\n");
//         size_t size = 0;
//         void *data = xRingbufferReceive(my_app.encoder_2_ws, &size, portMAX_DELAY);

//         xRingbufferSend(my_app.ws_2_decoder, data, size, portMAX_DELAY);

//         vRingbufferReturnItem(my_app.encoder_2_ws, data);
//     }
// }
void app_main(void)
{
    printf("Hello world!\n");
    display_init();

    int_led_init();
    int_led_off();
    bsp_wifi_init(); // 初始化wifi

    commu_ota_send_request(); // 发送ota请求
    bsp_sound_init();
    bsp_sound_open();
    app_create_buffer(); // 创建环形缓冲区

    audio_sr_init(); // 初始化语音识别

    audio_sr_start(my_app.sr_2_encoder, wake_up_callback, vad_state_change_callback); // 启动语音识别

    audio_encoder_init();                                          // 初始化编码器
    audio_encoder_start(my_app.sr_2_encoder, my_app.encoder_2_ws); // 启动编码器

    audio_decoder_init();                     // 初始化解码器
    audio_decoder_start(my_app.ws_2_decoder); // 启动解码器

    my_app.wait_hello_eg = xEventGroupCreate();

    commu_ws_init(text_cb, bin_cb, close_cb); // 初始化通信

    xTaskCreate(audio_upload_task, "audio_upload_task", 4096, NULL, 5, NULL);
    // xTaskCreate(test, "test", 4096, NULL, 5, NULL); // 创建测试任务

    display_show_tts("说:\"你好,小智\", 开始与小智进行对话");

    while (1)
    {
        vTaskDelay(10);
    }
}

void app_create_buffer(void)
{
    my_app.sr_2_encoder = xRingbufferCreateWithCaps(16 * 1024, RINGBUF_TYPE_BYTEBUF, MALLOC_CAP_SPIRAM);
    my_app.encoder_2_ws = xRingbufferCreateWithCaps(16 * 1024, RINGBUF_TYPE_NOSPLIT, MALLOC_CAP_SPIRAM);
    my_app.ws_2_decoder = xRingbufferCreateWithCaps(16 * 1024, RINGBUF_TYPE_NOSPLIT, MALLOC_CAP_SPIRAM);
}

void wake_up_callback(void)
{
    printf("wake up\n");

    switch (app_state)
    {
    case APP_IDLE:

        if (!my_ws.is_connected)
        {
            app_state = APP_CONNECTING;
            commu_ws_open_audio_channel();
            commu_ws_send_hello();
            xEventGroupWaitBits(my_app.wait_hello_eg, 1 << 0, true, true, portMAX_DELAY);
        }

        break;

    case APP_SPEAKING:
    {
        // 发送中指信息
        commu_ws_send_abort();
        break;
    }

    default:
        break;
    }

    app_state = APP_IDLE;
    // 发送唤醒词 TODO
    commu_ws_send_wake();
}

void vad_state_change_callback(vad_state_t state)
{
    // MY_LOGE("change: %s", state == VAD_SPEECH ? "speech" : "silence");
    if (state == VAD_SPEECH && app_state != APP_SPEAKING)
    {
        app_state = APP_LISTENING;
        // MY_LOGI("VAD_SPEECH->start listening");
        commu_ws_start_listening();
    }
    else if (state == VAD_SILENCE && app_state == APP_LISTENING)
    {
        app_state = APP_IDLE;
        // MY_LOGI("VAD_SILENCE->stop listening");
        commu_ws_stop_listening();
    }
}

void text_cb(char *text, int len)
{
    // MY_LOGI("text: %s", text);

    cJSON *root = cJSON_ParseWithLength(text, len);
    if (root == NULL)
    {
        MY_LOGE("parse failed");
        cJSON_Delete(root);
        return;
    }

    cJSON *type = cJSON_GetObjectItem(root, "type");
    if (type == NULL)
    {
        MY_LOGE("type not found");
        cJSON_Delete(root);
        return;
    }

    MY_LOGE("%.*s", len, text);

    if (strcmp(type->valuestring, "hello") == 0)
    {
        xEventGroupSetBits(my_app.wait_hello_eg, 1 << 0);
        commu_ws__send_iot_descriptor();
        commu_ws_send_iot_state();
    }
    else if (strcmp(type->valuestring, "tts") == 0)
    {
        cJSON *state = cJSON_GetObjectItem(root, "state");
        if (state == NULL)
        {
            MY_LOGE("state not found");
            cJSON_Delete(root);
            return;
        }
        if (strcmp(state->valuestring, "sentence_start") == 0)
        {
            app_state = APP_SPEAKING;
            //{"type":"tts","state":"sentence_start","text":"我只听我工程师男友的code指令，你谁啊？","session_id":"5b3d1e78"}
            // 获取text内容
            cJSON *text = cJSON_GetObjectItem(root, "text");
            if (text)
            {
                display_show_tts(text->valuestring);
            }
        }
        else if (strcmp(state->valuestring, "sentence_end") == 0)
        {
            app_state = APP_IDLE;
        }
    }

    else if (strcmp(type->valuestring, "llm") == 0)
    {
        cJSON *textItem = cJSON_GetObjectItem(root, "emotion");
        if (textItem)
        {
            char *text = textItem->valuestring;
            display_show_llm(text);
        }
    }

    else if (strcmp(type->valuestring, "iot") == 0)
    {
        //{"type":"iot","commands":[{"name":"Speaker","method":"SetVolume","parameters":{"volume":100}}],"session_id":"8392dab3"}
        // {"type":"iot","commands":[{"name":"Speaker","method":"SetMute","parameters":{"mute":true}}],"session_id":"1743365a"}

        // MY_LOGE("%.*s", len, text);
        // cJSON *commands = cJSON_GetObjectItem(root, "commands");
        // cJSON *command = cJSON_GetArrayItem(commands, 0);
        // // 从json中提取method和parameters中的volume
        // cJSON *method = cJSON_GetObjectItem(command, "method");
        // cJSON *parameters = cJSON_GetObjectItem(command, "parameters");
        // // cJSON *volume = cJSON_GetObjectItem(parameters, "volume");
        // if (strcmp(method->valuestring, "SetVolume") == 0)
        // {
        //     cJSON *volume = cJSON_GetObjectItem(parameters, "volume");
        //     bsp_sound_set_volume(volume->valueint);
        // }
        // else if (strcmp(method->valuestring, "SetMute") == 0)
        // {
        //     cJSON *muteItem = cJSON_GetObjectItem(parameters, "mute");
        //     bool mute = false;
        //     if (cJSON_IsBool(muteItem))
        //     {
        //         mute = cJSON_IsTrue(muteItem);
        //     }
        //     bsp_sound_set_mute(mute);
        // }

        cJSON *commands = cJSON_GetObjectItem(root, "commands");
        if (!cJSON_IsArray(commands))
        {
            return;
        }

        int count = cJSON_GetArraySize(commands);
        for (int i = 0; i < count; i++)
        {
            cJSON *cmd = cJSON_GetArrayItem(commands, i);
            cJSON *name = cJSON_GetObjectItem(cmd, "name");
            cJSON *method = cJSON_GetObjectItem(cmd, "method");
            cJSON *params = cJSON_GetObjectItem(cmd, "parameters");
            // if (!cJSON_IsString(name) || !cJSON_IsString(method) || !cJSON_IsObject(params))
            //     continue;

            if (strcmp(name->valuestring, "Speaker") == 0)
            {
                if (strcmp(method->valuestring, "SetVolume") == 0)
                {
                    cJSON *volume = cJSON_GetObjectItem(params, "volume");
                    if (cJSON_IsNumber(volume))
                    {
                        bsp_sound_set_volume(volume->valueint);
                    }
                }
                else if (strcmp(method->valuestring, "SetMute") == 0)
                {
                    cJSON *muteItem = cJSON_GetObjectItem(params, "mute");
                    if (cJSON_IsBool(muteItem))
                    {
                        bsp_sound_set_mute(cJSON_IsTrue(muteItem));
                    }
                }
            }
            else if (strcmp(name->valuestring, "Light") == 0)
            {
                if (strcmp(method->valuestring, "SetPower") == 0)
                {
                    cJSON *power = cJSON_GetObjectItem(params, "power");
                    if (cJSON_IsBool(power))
                    {
                        if (cJSON_IsTrue(power))
                        {
                            int_led_on();
                        }
                        else
                        {
                            int_led_off();
                        }
                    }
                }
            }
        }
    }
}
void bin_cb(char *bin, int len)
{
    if (my_app.ws_2_decoder)
    {
        xRingbufferSend(my_app.ws_2_decoder, bin, len, portMAX_DELAY);
    }
}
void close_cb(void)
{
    mt_sr.is_wake = false;
}

void audio_upload_task(void *args)
{

    while (1)
    {
        size_t size = 0;
        void *data = xRingbufferReceive(my_app.encoder_2_ws, &size, portMAX_DELAY);

        if (data && size > 0 && app_state == APP_LISTENING)
        {
            commu_ws_send_bin(data, size);
        }
        vRingbufferReturnItem(my_app.encoder_2_ws, data);
    }
}